package com.googlecode.connectlet.crypto.cipher.mode;

import com.googlecode.connectlet.crypto.cipher.Decipheror;

public class EcbNoPaddingDecipheror extends EcbCipher {
	protected Decipheror cipher;

	public EcbNoPaddingDecipheror(Decipheror cipher) {
		this.cipher = cipher;
		blockSize = cipher.getBlockSize();
		block = new byte[blockSize];
	}

	protected int decryptFirst(byte[] output, int outputOffset) {
		decryptNext(output, outputOffset);
		return blockSize;
	}

	protected void decryptNext(byte[] output, int outputOffset) {
		cipher.decrypt(block, 0, output, outputOffset);
	}

	@Override
	public int update(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) {
		int offset = inputOffset;
		int length = inputLen;
		if (blockOffset + length < blockSize) {
			System.arraycopy(input, offset, block, blockOffset, length);
			blockOffset += length;
			return 0;
		}
		int bytesRemain = blockSize - blockOffset;
		System.arraycopy(input, offset, block, blockOffset, bytesRemain);
		offset += bytesRemain;
		length -= bytesRemain;
		int bytesUpdated = decryptFirst(output, outputOffset);
		while (length >= blockSize) {
			System.arraycopy(input, offset, block, 0, blockSize);
			offset += blockSize;
			length -= blockSize;
			decryptNext(output, outputOffset + bytesUpdated);
			bytesUpdated += blockSize;
		}
		System.arraycopy(input, offset, block, 0, length);
		blockOffset = length;
		return bytesUpdated;
	}

	@Override
	public int doFinal(byte[] output, int outputOffset) {
		return 0;
	}
/*
	private static final int CIPHER_BUFFER_SIZE = 2048;

	public byte[] decrypt(byte[] iv, byte[] b) {
		return decrypt(iv, 0, b, 0, b.length);
	}

	public byte[] decrypt(byte[] iv, int ivOffset, byte[] b, int off, int len) {
		setBuffer(len);
		byte[] result = new byte[decrypt(iv, ivOffset, b, off, len, buffer, 0)];
		System.arraycopy(buffer, 0, result, 0, result.length);
		return result;
	}

	public int decrypt(byte[] iv, int ivOffset, byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) {
		init(iv, ivOffset);
		int outputLen = update(input, inputOffset, inputLen, output, outputOffset);
		return outputLen + doFinal(output, outputOffset + outputLen);
	}

	public InputStream decrypt(InputStream in, byte[] iv) {
		return decrypt(in, iv, 0);
	}

	public InputStream decrypt(final InputStream in, byte[] iv, int ivOffset) {
		init(iv, ivOffset);
		return new InputStream() {
			private byte[] output = null;
			private int outputOffset = 0, outputLen = 0;
			private boolean eof = false;

			@Override
			public int read() throws IOException {
				byte[] b = new byte[1];
				if (read(b, 0, 1) > 0) {
					return b[0] & 0xff;
				} else {
					return -1;
				}
			}

			@Override
			public int read(byte[] b, int off, int len) throws IOException {
				int bytesRead1 = Math.min(outputLen - outputOffset, len);
				if (bytesRead1 > 0) {
					System.arraycopy(output, outputOffset, b, off, bytesRead1);
					outputOffset += bytesRead1;
				}
				if (outputOffset < outputLen) {
					return bytesRead1;
				}
				if (eof) {
					return (bytesRead1 > 0 ? bytesRead1 : -1);
				}

				if (setBuffer(len - bytesRead1)) {
					output = new byte[buffer.length];
				}

				int bytesRead2 = in.read(buffer);
				if (bytesRead2 > 0) {
					outputLen = update(buffer, 0, bytesRead2, output, 0);
				} else {
					outputLen = doFinal(output, 0);
					eof = true;
				}
				bytesRead2 = Math.min(outputLen, len - bytesRead1);
				System.arraycopy(output, 0, b, off + bytesRead1, bytesRead2);
				outputOffset = bytesRead2;
				if (bytesRead1 + bytesRead2 == 0) {
					return read(b, off, len);
				}
				return bytesRead1 + bytesRead2;
			}

			@Override
			public void close() throws IOException {
				in.close();
			}
		};
	}

	protected boolean setBuffer(int len) {
		int bufferSize = (len + blockSize * 2 + CIPHER_BUFFER_SIZE) / CIPHER_BUFFER_SIZE * CIPHER_BUFFER_SIZE;
		if (buffer == null || buffer.length < bufferSize) {
			buffer = new byte[bufferSize];
			return true;
		} else {
			return false;
		}
	}
*/
}